たった23行で Amazon ECS にデプロイできた。あらゆるプラットフォームでアプリケーションをビルド、デプロイする Waypoint を使ってみた。
先日、Terraform でお馴染みの HashiCorp 社から ”Waypoint" という新たなオープンソースプロジェクトが発表されました。
アプリケーションのビルド、デプロイ、リリースといったワークフローを、Kubernetes/AWS/GCP/Azure など 12 以上のプラットフォームで利用可能。マルチプラットフォームに対応しているだけならば同様のツールはあるかもしれませんが、Waypoint は各プラットフォームごとのお作法などを抽象化し、開発者にインフラを意識させることなくデプロイ出来ることを目指したツールのようです。(位置づけてきに Spinnaker に近い?)
まだプロジェクトの初期ということで本番環境で利用できるものではないと思いますが、ひとまず ECS へのデプロイをサクッと試してみました。
Waypoint とは
まずは Waypoint のコンセプトや目標について簡単に説明します。 (以降の内容は Waypoint の開発に至った背景やプロジェクトの目標です。執筆時点では提供されていない機能も含んでいる点、ご注意ください。)
Waypoint が目指すところ
- ワークフローの標準化
- Waypoint は、アプリケーションを開発から本番環境へと移行するための使いやすく一貫性のあるワークフローを提供することを目指しています。プラットフォームに基づくワークフローの断片化は複数のビルド、デプロイ、リリースツールを使用しようとするチームにとって大きな課題です
- デプロイに確信をもつ
- デプロイ後に開発者が最初に行うことは、ブラウザを開いたり、ページを更新したり、ログをチェックしたりと、動作を確認することです。Waypoint はバージョン管理可能な検証用の URLや、シェルスクリプトを介してリモートコマンドを実行する exec、デバッグ用の一時ログセットなどを提供し、デプロイが成功したことを確信できるようにします
- エコシステムによる拡張性
- Waypoint は、カスタムビルダーやデプロイメントプラットフォームなどを取り入れることができるプラグインを介して完全に拡張可能です
なぜ Waypoint?
Waypoint は以下のような問題を解決します
- 「デプロイしたいだけやねんけど」問題
- 開発のパターンがコンテナ、スケジューラ、YAML ファイル、サーバーレスなど複雑さに溢れていることが現実。最初のアプリケーションをデプロイするまでに学習コストがかかります。Waypoint はプラットフォームの違いをラップします。
- 「ツール多すぎんねん」問題
- もう 1 つの課題はアプリケーションをデプロイする場所によって使用するツールが異なるということ。Kubernetes には kubectl と Docker、VM には Packer と Terraform、各サーバーレスにはカスタム CLI など。このような現実が個人においては学習コスト、チームにとっては一貫性という課題をもたらしています。Waypoint はこれらの環境をラップし、オーケストレーターとして機能することでワークフローを標準化します。
使いやすさの提供
Waypoint は使いやすさを提供するために作られました。もう Dockerfile や YAML を書く必要はない。言語を自動検出し、イメージをビルドし、デプロイするためのプラグインも用意されている。最低限の設定を書く必要はあるが、1 つのツールで 15 行程度で済みます。
どんなプラットフォームでも
Waypoint はどんなプラットフォームでも一貫性があるように構築されている。プラグインを使って拡張が可能であり、あらゆるビルド、デプロイ、リリースのロジックをターゲットにすることができます。また、Waypoint そのものは継続的インテグレーションやテスト自動化を提供するものではなく、既存のそういったツールのラッパーでありオーケストレーターという位置づけのようです。
「開発者は、ただデプロイをしたいだけです。Waypoint はそれを実現します」
とても魅力的なメッセージですね。
やってみる
Waypoint が目指している方向性を理解したところで、さっそく触ってみましょう。
事前準備
- Amazon ECS へのデプロイを検証します。該当の AWS アカウントで十分な IAM 権限を持っていることを前提としています。(今回は
Administrator
権限で検証しています) - 今回、ビルドのアーティファクト の push 先に ECR を利用します。ECR は事前に作成済みとします。
インストール
Waypoint は Windows, Linux, Mac OS X の環境で動作します。今回は公式ガイドの Homebrew on OS X 手順に従ってインストールします。
$ brew --version Homebrew 2.5.6 Homebrew/homebrew-core (git revision d1b6d; last commit 2020-10-19) Homebrew/homebrew-cask (git revision b0b12; last commit 2020-10-19) # Hashicorp のリポジトリを追加 $ brew tap hashicorp/tap Updating Homebrew... ==> Tapping hashicorp/tap Cloning into '/usr/local/Homebrew/Library/Taps/hashicorp/homebrew-tap'... remote: Enumerating objects: 176, done. remote: Counting objects: 100% (176/176), done. remote: Compressing objects: 100% (103/103), done. remote: Total 585 (delta 89), reused 154 (delta 73), pack-reused 409 Receiving objects: 100% (585/585), 113.37 KiB | 331.00 KiB/s, done. Resolving deltas: 100% (256/256), done. Tapped 8 formulae (44 files, 192KB). # インストール Updating Homebrew... ==> Installing waypoint from hashicorp/tap ==> Downloading https://releases.hashicorp.com/waypoint/0.1.2/waypoint_0.1.2_darwin_amd64.zip ######################################################################## 100.0% /usr/local/Cellar/waypoint/0.1.2: 3 files, 141.7MB, built in 5 seconds ==> `brew cleanup` has not been run in 30 days, running now... Removing: /Users/marumo.atsushi/Library/Caches/Homebrew/cert--0.15.0.tar.gz... (2.1MB) Removing: /Users/marumo.atsushi/Library/Caches/Homebrew/krb5--1.18.1.catalina.bottle.tar.gz... (1.3MB) Removing: /Users/marumo.atsushi/Library/Caches/Homebrew/libpq--12.2_1.catalina.bottle.tar.gz... (5.9MB) Removing: /Users/marumo.atsushi/Library/Caches/Homebrew/openssl@1.1--1.1.1g.catalina.bottle.tar.gz... (5.3MB) Removing: /Users/marumo.atsushi/Library/Logs/Homebrew/krb5... (64B) Removing: /Users/marumo.atsushi/Library/Logs/Homebrew/gettext... (64B) Removing: /Users/marumo.atsushi/Library/Logs/Homebrew/cert... (115B) Removing: /Users/marumo.atsushi/Library/Logs/Homebrew/libpq... (64B) Removing: /Users/marumo.atsushi/Library/Logs/Homebrew/pcre2... (64B) Removing: /Users/marumo.atsushi/Library/Logs/Homebrew/openssl@1.1... (64B) Removing: /Users/marumo.atsushi/Library/Logs/Homebrew/git... (64B) Pruned 1 symbolic links and 2 directories from /usr/local $ waypoint version Waypoint v0.1.2 (edf37a09)
これで実行環境は整いました。
Amazon ECS にデプロイ
以下のチュートリアルに従って進めます。(ほかに Kubernetes、Google Cloud、Azure といったチュートリアルもあるので、興味のある方はお試しください)
git からサンプルプロジェクトを clone し、ECS 用のサブディレクトリに移動します。
$ git clone https://github.com/hashicorp/waypoint-examples.git $ cd ./waypoint-examples/aws-ecs/nodejs $ tree . ├── Procfile ├── README.md ├── index.js ├── package.json ├── public │ ├── hashi.svg │ ├── language.svg │ ├── logo.svg │ ├── pattern-br.svg │ ├── pattern-tl.svg │ └── stylesheets │ └── main.css ├── views │ ├── pages │ │ └── index.ejs │ └── partials │ └── header.ejs └── waypoint.hcl
waypoint.hcl
waypoint.hcl
は Waypoint の設定ファイルです。ビルド、デプロイ、リリースのワークフローをこの設定ファイル 1 つで定義します。驚くべきはコード量の少なさですね。空の行を除くとわずか 23 行です。シンプルなチュートリアルとはいえ、少なすぎる!!
project = "example-nodejs" app "example-nodejs" { labels = { "service" = "example-nodejs", "env" = "dev" } build { use "pack" {} registry { use "aws-ecr" { region = "ap-northeast-1" repository = "waypoint-example" tag = "latest" } } } deploy { use "aws-ecs" { region = "ap-northeast-1" memory = "512" } } }
ざっくり説明すると、build
スタンザで Waypoint がアプリをビルドする方法を定義します。use "pack"
オプションは Cloud Native Buildpack を使用してアプリケーションをビルドするように指示しています。
registry
スタンザはビルドしたアーティファクトの push 先を指定します。この例では use "aws-ecr"
を指定し ECR に push します。
deploy
スタンザはビルドで作成したアーティファクトを取得、ターゲットプラットフォームにデプロイします。この例では ap-northeast-1
の ECS へのデプロイを指示しています。memory
のみ指定していますが subnet
、alb
、log_group
などの指定も可能です。(その他のオプションはこちらを参照)
また、以下のようなプラットフォームの指定が可能です。
- Kubernetes
- AWS EKS、Azure AKS、Google GKE、Kubernetes for Docker Desktopなど
- HashiCorp Nomad
- AWS EC2
- AWS ECS
- Google Cloud Run
- Azure Container Instances
- Netlify
その他にも hook
スタンザを使用してビルドやデプロイの前後にコマンドやスクリプトを実行することが可能です。
ローカル Waypoint サーバーのインストール
Waypoint サーバーはデータを保存し、ビルド、デプロイなどの操作をオーケストレーションするサーバーです。グループなどメンバーで利用する場合は 1 つの(共通の) Waypoint サーバーを利用する必要がありますが、今回は個人利用なのでローカルサーバーとして、Mac 内の Docker に Waypoint サーバーを作成します。
まずは Docker イメージをダウンロードします。
$ docker pull hashicorp/waypoint:latest latest: Pulling from hashicorp/waypoint df20fa9351a1: Pull complete 464c4c2e60be: Pull complete 802d9b65569c: Pull complete Digest: sha256:689cae07ac8836ceba1f49c0c36ef57b27ebf61d36009bc309d2198e7825beb9 Status: Downloaded newer image for hashicorp/waypoint:latest docker.io/hashicorp/waypoint:latest $ docker images hashicorp/waypoint REPOSITORY TAG IMAGE ID CREATED SIZE hashicorp/waypoint latest 3792b8e01ae0 2 days ago 145MB
次に、install
コマンドでローカルの Docker インスタンスに Waypoint サーバーをインストールします。Waypoint サーバーを Kubenetes にすることも出来ます。(accept-tos
は利用規約への同意フラグです)
$ waypoint install --platform=docker -accept-tos ✓ Server container started Waypoint server successfully installed and configured! The CLI has been configured to connect to the server automatically. This connection information is saved in the CLI context named "install-1603095163". Use the "waypoint context" CLI to manage CLI contexts. The server has been configured to advertise the following address for entrypoint communications. This must be a reachable address for all your deployments. If this is incorrect, manually set it using the CLI command "waypoint server config-set". Advertise Address: waypoint-server:9701 HTTP UI Address: https://localhost:9702
https://localhost:9702
は Waypoint サーバーへのアクセス URL になります。
Waypoint サーバーへのログインは waypoint token new
コマンドで取得した token を入力し、Authenticate with Token
をクリック。
Waypoint を初期化
アプリケーションをビルドしてデプロイする前に init
コマンドでプロジェクトを初期化します。初期化プロセスでは、アプリケーションディレクトリ内の Waypoint 構成ファイル waypoint.hcl
を探します。構成ファイルが存在しない場合は、スターターファイルとしての waypoint.hcl
を作成します。
$ waypoint init ✓ Configuration file appears valid ✓ Connection to Waypoint server was successful ✓ Project "example-nodejs" and all apps are registered with the server. ✓ Plugins loaded and configured successfully ✓ Authentication requirements appear satisfied. Project initialized! You may now call 'waypoint up' to deploy your project or commands such as 'waypoint build' to perform steps individually.
アプリケーションのビルド、デプロイ、リリース
up
コマンドでアプリケーションをビルド、デプロイします。
$ waypoint up » Building... Creating new buildpack-based image using builder: heroku/buildpacks:18 ✓ Creating pack client ✓ Building image │ [exporter] Adding 1/1 app layer(s) │ [exporter] Adding layer 'launcher' │ [exporter] Adding layer 'config' │ [exporter] Adding label 'io.buildpacks.lifecycle.metadata' │ [exporter] Adding label 'io.buildpacks.build.metadata' │ [exporter] Adding label 'io.buildpacks.project.metadata' │ [exporter] *** Images (35082e96dc14): │ [exporter] index.docker.io/library/example-nodejs:latest │ [exporter] Adding cache layer 'heroku/nodejs-engine:nodejs' │ [exporter] Adding cache layer 'heroku/nodejs-engine:toolbox' ✓ Injecting entrypoint binary to image Creating new buildpack-based image using builder: heroku/buildpacks:18 ✓ Creating pack client✓ Building image │ [exporter] Adding 1/1 app layer(s) │ [exporter] Adding layer 'launcher' │ [exporter] Adding layer 'config' │ [exporter] Adding label 'io.buildpacks.lifecycle.metadata' │ [exporter] Adding label 'io.buildpacks.build.metadata' │ [exporter] Adding label 'io.buildpacks.project.metadata' │ [exporter] *** Images (35082e96dc14): │ [exporter] index.docker.io/library/example-nodejs:latest │ [exporter] Adding cache layer 'heroku/nodejs-engine:nodejs' │ [exporter] Adding cache layer 'heroku/nodejs-engine:toolbox' ✓ Injecting entrypoint binary to image Generated new Docker image: example-nodejs:latest Tagging Docker image: example-nodejs:latest => 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/waypoint-example:latest Docker image pushed: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/waypoint-example:latest » Deploying... ✓ Created new ECS cluster: waypoint ✓ Created IAM role: ecr-example-nodejs ✓ Created CloudWatchLogs group to store logs in: waypoint-logs ✓ Created ALB target group ✓ Created new ALB Listener ✓ Configured security group: example-nodejs-inbound-internal ✓ Created ECS Service (example-nodejs-A8Q6ECFPE8G9R2R5G, cluster-name: waypoint) » Releasing... The deploy was successful! A Waypoint deployment URL is shown below. This can be used internally to check your deployment and is not meant for external traffic. You can manage this hostname using "waypoint hostname." Release URL: http://waypoint-ecs-example-nodejs-397207959.ap-northeast-1.elb.amazonaws.com Deployment URL: https://manually-prepared-sawfish--v1.waypoint.run
http://waypoint-ecs-example-nodejs-397207959.ap-northeast-1.elb.amazonaws.com
にアクセスして、正常にデプロイされたことを確認します。
Deployment URL では Let's Encrypt で自動的に生成された証明書を利用し、デプロイしたアプリケーションを素早く表示したり、他の人とアプリケーションを共有したりすることができるそうなのですが、なぜだか表示できませんでした。まだリリース初期であるためバグなのか、設定が足りていないのか判断することが出来ず今回はスルーしました。
AWS 環境の確認
up
コマンドのログからもわかるように、以下のようなリソースが作成されています。
- ECS タスク、サービス、クラスター
- IAM ロール
- CloudwatchLogs グループ
- ALB、ターゲットグループ
- セキュリティグループ
いくつか確認してみましょう。まずは ECR ですが、ビルドされたイメージが push されてます。
次に ECS ですが、クラスターやサービスが作成され、タスクが起動しています。今回のサンプルですと Fargate で起動していました。VPC は特に指定していなかったので default VPC で起動しています。
セキュリティグループも自動的に作成されています。
ELB は、ALB が作成されリスナーやターゲットグループが設定されています。
Waypoint サーバーを確認
https://localhost:9702
にアクセスし、Waypoint サーバーを確認してみるとプロジェクトが追加されています。
example-nodejs
をクリック すると、このようなダッシュボードが表示されます。
ビルド時のログがなども確認できます。
ちなみに Exec タブからリモートコマンドの実行もできるようですが、こちらの機能はまだ提供されていないようです。
環境の破棄
destory
コマンドでプロビジョニングを解除します。destroy
コマンドは、レジストリまたは ECS クラスター自体のコンテナーイメージを削除しません。ECR コンソールにアクセスして、レジストリ全体または個々のコンテナイメージを手動で削除します。
$ waypoint destroy Destroy successful!
と書きましたが、現状はまだ動作しないようなので、後片付けは手作業でやりましょ。。
さいごに
プラットフォームのインフラ部分を意識せずにデプロイのみに集中したい開発者の方は、是非一度触っていただきたいです。
逆に細かい設定部分までをコントロールしたいユーザーには抽象度が高すぎるかもしれません。
Waypoint はまだリリースされたばかりなので、その実力をはかるには、もうしばらく時間が必要かと思いますが今後の展開から目を離せないサービスであることは間違いなさそうです!ロードマップの一部は以下で公開されています。
今回はチュートリアルを実行しただけですので、次はもう少し AWS の観点でどこまでの設定ができるのか試してみたいと思います。
以上!大阪オフィスの丸毛(@marumo1981)でした!